#pragma once

#include "TemplateableElement.h"

#include "ParameterableElement.h"
#include "TemplateBinding.h"
#include "TemplateSignature.h"

namespace uml {

void TemplateableElement::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    PartialElement::fromJson(json, errorList);
    ownedTemplateSignature_ = JsonSerializable::create<TemplateSignature>(json.value("ownedTemplateSignature"), errorList);

    JsonSerializable::fromJsonArray(templateBindings_, "templateBindings", json, errorList);
}

void TemplateableElement::toJson(QJsonObject& json) {
    PartialElement::toJson(json);
    if (ownedTemplateSignature_) {
        QJsonObject ownedTemplateSignature_json;
        ownedTemplateSignature_->toJson(ownedTemplateSignature_json);
        json.insert("ownedTemplateSignature", ownedTemplateSignature_json);
    }
    JsonSerializable::toJsonArray(templateBindings_, "templateBindings", json);
}

/// <summary>
/// isTemplate
    /// The query isTemplate() returns whether this TemplateableElement is actually a
    /// template.
/// </summary>
    /// <code>
    /// result = (ownedTemplateSignature <> null)
    /// </code>
bool TemplateableElement::isTemplate() const
{
    return false;
}

/// <summary>
/// parameterableElements
    /// The query parameterableElements() returns the set of ParameterableElements that
    /// may be used as the parameteredElements for a TemplateParameter of this
    /// TemplateableElement. By default, this set includes all the ownedElements.
    /// Subclasses may override this operation if they choose to restrict the set of
    /// ParameterableElements.
/// </summary>
    /// <code>
    /// result = (self.allOwnedElements()->select(oclIsKindOf(ParameterableElement)).oclAsType(ParameterableElement)->asSet())
    /// </code>
shared_ptr<vector<ParameterableElement>> TemplateableElement::parameterableElements() const
{
    return nullptr;
}

/// <summary>
/// ownedTemplateSignature getter
/// The optional TemplateSignature specifying the formal TemplateParameters for this
/// TemplateableElement. If a TemplateableElement has a TemplateSignature, then it
/// is a template.
/// </summary>
shared_ptr<TemplateSignature> TemplateableElement::ownedTemplateSignature() const {
    return ownedTemplateSignature_;
}

/// <summary>
/// ownedTemplateSignature setter
/// The optional TemplateSignature specifying the formal TemplateParameters for this
/// TemplateableElement. If a TemplateableElement has a TemplateSignature, then it
/// is a template.
/// </summary>
void TemplateableElement::setOwnedTemplateSignature(shared_ptr<TemplateSignature> value) {
    ownedTemplateSignature_ = value;
}

/// <summary>
/// templateBindings getter
/// The optional TemplateBindings from this TemplateableElement to one or more
/// templates.
/// </summary>
vector<shared_ptr<TemplateBinding>>& TemplateableElement::templateBindings() {
    return templateBindings_;
}

} // namespace uml
